import re
import sqlite3
import hashlib
import tkinter as tk
from datetime import datetime
from PIL import Image, ImageTk
from ttkbootstrap.constants import *
from tkinter.messagebox import showerror, showinfo
from ttkbootstrap import Frame, Button, Label, Entry, Combobox, Notebook, Checkbutton


class LoginRegister:
    def __init__(self):
        # 设置窗口的宽度和高度
        self.login_register_win_width = 660
        self.login_register_win_height = 410
        self.other_win_width = 1120
        self.other_win_height = 560
        # 图片地址
        self.wx_code_image = "./images/1.jpg"
        # 数据库地址
        self.db_path = "./info.db"
        # 登录和注册框架
        self.register_login = tk.Tk()
        # 登录信息
        self.login_phone = None
        self.login_psw = None
        self.remember_psw = None
        # 注册组件，方便清空数据
        self.register_username_entry = None
        self.register_phone_entry = None
        self.register_psw_entry = None
        self.register_combox = None
        # 注册内容
        self.register_username = None
        self.register_psw = None
        self.register_id = None
        self.register_pone = None

    def create_window(self):
        # 设备屏幕的宽度和高度
        screen_width = self.register_login.winfo_screenwidth()
        screen_height = self.register_login.winfo_screenheight()
        # 设置窗口打开的x，y位置
        x = int((screen_width - self.login_register_win_width) / 2)
        y = int((screen_height - self.login_register_win_height) / 2)
        # 窗口标题
        self.register_login.title("登录&注册")
        self.register_login.geometry(
            "%sx%s+%s+%s" % (self.login_register_win_width, self.login_register_win_height, x, y))
        # 设置窗口宽高固定
        self.register_login.resizable(0, 0)
        # 设置窗口图标
        self.register_login.iconbitmap("./images/login.ico")

        # 登录和注册界面
        notebook = Notebook(self.register_login, bootstyle="primary")
        register_frame = Frame(self.register_login)
        login_frame = Frame(self.register_login)
        notebook.add(login_frame, text="账号密码登录")
        notebook.add(register_frame, text="账号密码注册")
        notebook.place(x=150, y=80)
        # 登录内容
        self.login_window(login_frame)
        # 注册内容
        self.register_window(register_frame)
        self.register_login.mainloop()

    def login_window(self, frame=None):
        # 用户名输入框
        username_label = Label(frame, text="手机号：")
        username_label.grid(row=1, column=1, padx=5, pady=20)
        self.login_phone = tk.StringVar()
        username_entry = Entry(frame, bootstyle=INFO, textvariable=self.login_phone, width=30)
        username_entry.grid(row=1, column=2, padx=5, pady=10)
        # 密码输入框
        psw_label = Label(frame, text="密    码：")
        psw_label.grid(row=2, column=1, padx=5, pady=10)
        self.login_psw = tk.StringVar()
        psw_entry = Entry(frame, bootstyle=INFO, textvariable=self.login_psw, show="*", width=30)
        psw_entry.grid(row=2, column=2, padx=5, pady=10)
        # 记住密码选项
        self.remember_psw = tk.IntVar()
        pwd_check_button = Checkbutton(frame, text="记住密码", variable=self.remember_psw)
        pwd_check_button.grid(row=3, column=1, padx=5, pady=5, columnspan=2, sticky="w")
        # 登录按钮
        login_button = Button(frame, text="登  录", bootstyle=PRIMARY, width=40, command=self.login)
        login_button.grid(row=4, column=1, padx=5, pady=10, columnspan=2)
        # 查看是否记住密码
        remember_select_sql = """SELECT phone,password,is_remember FROM remember_psw WHERE id=1;"""
        is_remember = self.execute_sql(remember_select_sql)
        if is_remember:
            if is_remember[0][2] == "1":
                self.login_phone.set(is_remember[0][0])
                self.login_psw.set(is_remember[0][1])
                self.remember_psw.set(int(is_remember[0][2]))

    def register_window(self, frame=None):
        padx = 5
        pady = 5
        # 用户名输入框
        username_label = Label(frame, text="用户名：")
        username_label.grid(row=1, column=1, padx=padx, pady=pady)
        self.register_username = tk.StringVar()
        self.register_username_entry = Entry(frame, bootstyle=INFO, textvariable=self.register_username, width=30)
        self.register_username_entry.grid(row=1, column=2, padx=padx, pady=pady)
        # 手机号输入框
        username_label = Label(frame, text="手机号：")
        username_label.grid(row=2, column=1, padx=padx, pady=pady)
        self.register_pone = tk.StringVar()
        self.register_phone_entry = Entry(frame, bootstyle=INFO, textvariable=self.register_pone, width=30)
        self.register_phone_entry.grid(row=2, column=2, padx=padx, pady=pady)
        # 密码输入框
        psw_label = Label(frame, text="密    码：")
        psw_label.grid(row=3, column=1, padx=padx, pady=pady)
        self.register_psw = tk.StringVar()
        self.register_psw_entry = Entry(frame, bootstyle=INFO, textvariable=self.register_psw, show="*", width=30)
        self.register_psw_entry.grid(row=3, column=2, padx=padx, pady=pady)
        # 身份
        psw_label = Label(frame, text="身    份：")
        psw_label.grid(row=4, column=1, padx=padx, pady=pady)
        self.register_id = tk.StringVar()
        self.register_combox = Combobox(frame, bootstyle=PRIMARY, textvariable=self.register_id, state="readonly",
                                        width=28)
        self.register_combox["value"] = ("下拉选择身份：", "教师", "学生")
        self.register_combox.current(0)
        self.register_combox.grid(row=4, column=2, padx=padx, pady=pady)
        # 登录按钮
        login_button = Button(frame, text="注  册", bootstyle=PRIMARY, width=40, command=self.register)
        login_button.grid(row=5, column=1, padx=padx, pady=pady, columnspan=2)

    def login(self):
        phone = self.login_phone.get()
        password = self.login_psw.get()
        remember = self.remember_psw.get()
        if phone and password:
            md5_password = self.encryption(password)
            select_sql = f"""select 1 from users where phone='{phone}' AND password_md5='{md5_password}';"""
            if self.execute_sql(select_sql):
                create_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                # 更新记住密码操作
                update_sql = f"""UPDATE remember_psw SET phone='{phone}',password='{password}',is_remember='{remember}',create_time='{create_time}' WHERE id=1;"""
                self.execute_sql(update_sql)
                # showinfo(title="登录", message="登录成功！")
                self.register_login.destroy()
                # 根据登录的身份打开不同的界面
                select_id_sql = f"""SELECT name,identity FROM users WHERE phone='{phone}';"""
                select_id_result = self.execute_sql(select_id_sql)
                if select_id_result[0][1] == "管理员":
                    self.admin_window()
                elif select_id_result[0][1] == "教师":
                    self.teacher_window()
                elif select_id_result[0][1] == "学生":
                    self.student_window()
            else:
                showerror(title="失败", message="账号密码输入错误！")
        else:
            showerror(title="失败", message="账号密码输入有误！")

    def register(self):
        user_name = self.register_username.get()
        phone = self.register_pone.get()
        password = self.register_psw.get()
        identity = self.register_id.get()
        if user_name and phone and password and (identity in ("教师", "学生")):
            if not re.match(r"^1[356789]\d{9}$", phone):
                showerror(title="失败", message="手机号填写有误！")
            elif not (password.isalnum() and len(password) >= 6):
                showerror(title="失败", message="密码至少6位且由数字、字母组成！")
            else:
                # 判断手机号是否存在
                select_sql = f"""select 1 from users where phone='{phone}' LIMIT 1;"""
                if self.execute_sql(select_sql):
                    # 手机号已注册
                    showerror(title="失败", message="该手机号已注册！")
                else:
                    md5_password = self.encryption(password)
                    create_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    insert_users_sql = f"""
                    INSERT INTO users (name,phone,password,password_md5,identity,create_time) VALUES ('{user_name}','{phone}','{password}','{md5_password}','{identity}','{create_time}');
                    """
                    self.execute_sql(insert_users_sql)
                    insert_remember_psw_sql = f"""
                    INSERT INTO remember_psw (phone,password,is_remember,create_time) VALUES ('{phone}','{password}','0','{create_time}');
                    """
                    self.execute_sql(insert_remember_psw_sql)
                    showinfo(title="注册", message="注册成功！")
                    self.register_username_entry.delete(0, "end")
                    self.register_phone_entry.delete(0, "end")
                    self.register_psw_entry.delete(0, "end")
                    self.register_combox.current(0)
        else:
            showerror(title="失败", message="信息未填写完整！")

    def admin_window(self):
        """
        管理员界面
        """
        admin = tk.Tk()
        # 设备屏幕的宽度和高度
        screen_width = admin.winfo_screenwidth()
        screen_height = admin.winfo_screenheight()
        # 设置窗口打开的x，y位置
        x = int((screen_width - self.other_win_width) / 2)
        y = int((screen_height - self.other_win_height) / 2)
        # 窗口标题
        admin.title("管理员界面")
        admin.geometry("%sx%s+%s+%s" % (self.other_win_width, self.other_win_height, x, y))
        # 设置窗口图标
        admin.iconbitmap("./images/admin.ico")
        # 图片保存地址
        admin.mainloop()

    def teacher_window(self):
        teacher = tk.Tk()
        # 设备屏幕的宽度和高度
        screen_width = teacher.winfo_screenwidth()
        screen_height = teacher.winfo_screenheight()
        # 设置窗口打开的x，y位置
        x = int((screen_width - self.other_win_width) / 2)
        y = int((screen_height - self.other_win_height) / 2)
        # 窗口标题
        teacher.title("教师界面")
        teacher.geometry("%sx%s+%s+%s" % (self.other_win_width, self.other_win_height, x, y))
        # 设置窗口图标
        teacher.iconbitmap("./images/teacher.ico")
        teacher.mainloop()

    def student_window(self):
        student = tk.Tk()
        # 设备屏幕的宽度和高度
        screen_width = student.winfo_screenwidth()
        screen_height = student.winfo_screenheight()
        # 设置窗口打开的x，y位置
        x = int((screen_width - self.other_win_width) / 2)
        y = int((screen_height - self.other_win_height) / 2)
        # 窗口标题
        student.title("学生界面")
        student.geometry("%sx%s+%s+%s" % (self.other_win_width, self.other_win_height, x, y))
        # 设置窗口图标
        student.iconbitmap("./images/student.ico")
        student.mainloop()

    def execute_sql(self, sql):
        """
        执行sql语句
        """
        conn = sqlite3.connect(self.db_path)
        c = conn.cursor()
        if sql.lower().startswith("select"):
            cursor = c.execute(sql)
            result = cursor.fetchall()
            conn.commit()
            conn.close()
            return result
        c.execute(sql)
        conn.commit()
        conn.close()

    def encryption(self, string, encry_model="md5_32", encry_style=True):
        # 加密为 utf-8 编码
        utf_8_str = str(string).encode("utf8")
        # 函数字典
        param_dict = {
            "md5_32": hashlib.md5(utf_8_str),
            "md5_16": hashlib.md5(utf_8_str),
            "sha1": hashlib.sha1(utf_8_str),
            "sha224": hashlib.sha224(utf_8_str),
            "sha256": hashlib.sha256(utf_8_str),
            "sha512": hashlib.sha512(utf_8_str)
        }
        encry_result = param_dict[encry_model].hexdigest()
        if encry_model == 'md5_16':
            encry_result = encry_result[8:-8]
        # 返回结果
        return encry_result if encry_style == "小写" else encry_result.upper()


if __name__ == '__main__':
    """
    管理员手机号：admin，密码：admin
    """
    lr = LoginRegister()
    lr.create_window()
